---
import Select from "@astrojs/starlight/components/Select.astro";
---

<starlight-theme-select>
  {
    /* TODO: Can we give this select a width that works well for each language’s strings? */
  }
  <Select
    icon="laptop"
    label={Astro.locals.t("themeSelect.accessibleLabel")}
    options={[
      {
        label: Astro.locals.t("themeSelect.dark"),
        selected: false,
        value: "dark",
      },
      {
        label: Astro.locals.t("themeSelect.light"),
        selected: false,
        value: "light",
      },
      {
        label: Astro.locals.t("themeSelect.auto"),
        selected: true,
        value: "auto",
      },
    ]}
    width="20px"
  />
</starlight-theme-select>

{/* Inlined to avoid FOUC. Uses global scope from `ThemeProvider.astro` */}
<script is:inline>
  StarlightThemeProvider.updatePickers();
</script>

<script>
  type Theme = "auto" | "dark" | "light";

  /** Key in `localStorage` to store color theme preference at. */
  const storageKey = "starlight-theme";

  /** Get a typesafe theme string from any JS value (unknown values are coerced to `'auto'`). */
  const parseTheme = (theme: unknown): Theme =>
    theme === "auto" || theme === "dark" || theme === "light" ? theme : "auto";

  /** Load the user’s preference from `localStorage`. */
  const loadTheme = (): Theme =>
    parseTheme(
      typeof localStorage !== "undefined" && localStorage.getItem(storageKey),
    );

  /** Store the user’s preference in `localStorage`. */
  function storeTheme(theme: Theme): void {
    if (typeof localStorage !== "undefined") {
      localStorage.setItem(
        storageKey,
        theme === "light" || theme === "dark" ? theme : "",
      );
    }
  }

  /** Get the preferred system color scheme. */
  const getPreferredColorScheme = (): Theme =>
    matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";

  /** Update select menu UI, document theme, and local storage state. */
  function onThemeChange(theme: Theme): void {
    StarlightThemeProvider.updatePickers(theme);
    document.documentElement.dataset.theme =
      theme === "auto" ? getPreferredColorScheme() : theme;
    storeTheme(theme);
  }

  // React to changes in system color scheme.
  matchMedia(`(prefers-color-scheme: light)`).addEventListener("change", () => {
    if (loadTheme() === "auto") onThemeChange("auto");
  });

  class StarlightThemeSelect extends HTMLElement {
    constructor() {
      super();
      onThemeChange(loadTheme());
      this.querySelector("select")?.addEventListener("change", (e) => {
        if (e.currentTarget instanceof HTMLSelectElement) {
          onThemeChange(parseTheme(e.currentTarget.value));
        }
      });
    }
  }
  customElements.define("starlight-theme-select", StarlightThemeSelect);
</script>
